package com.sd.repay.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.sd.repay.common.CommonResult;
import com.sd.repay.common.Constants;
import com.sd.repay.dao.BaseDao;
import com.sd.repay.pojo.PayOrder;
import com.sd.repay.pojo.ProfitDetail;
import com.sd.repay.pojo.RepayPlan;
import com.sd.repay.pojo.RepayPlanDetail;
import com.sd.repay.service.*;
import com.sd.repay.utils.DateUtil;
import com.sd.repay.utils.JsonUtil;
import com.sd.repay.utils.StringUtil;
import com.sd.repay.utils.WebUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Service
public class AroundPayOrderServiceImpl implements AroundPayOrderService {

    private static Logger log = LoggerFactory.getLogger(AroundPayOrderServiceImpl.class);

    @Autowired
    private BaseDao baseDao;
    @Autowired
    private PayOrderService payOrderService;
    @Autowired
    private MerchantService merchantService;
    @Autowired
    private CardManageService cardService;
    @Autowired
    private RepayPlanService planService;
    @Autowired
    private RepayPlanDetailService planDetailService;
    @Autowired
    private MerFeeService merFeeService;
    @Autowired
    private ProfitDetailService profitService;
    @Autowired
    private BalanceOperService balanceOperService;
    @Autowired
    private RankService rankService;

    /**
     * 新增订单前的统一操作
     *
     * @param merchantNo
     * @param cardNo
     * @param planNo
     * @param transAmount
     * @param acqCode
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public CommonResult prePayOrder(String merchantNo, String cardNo, String planNo, String transAmount, String acqCode) throws Exception {

        //获取商户信息
        Map<String, Object> merMap = merchantService.getMerInfoByMerNo(merchantNo);
        log.info(merchantNo + "商户号对应商户信息：" + JsonUtil.objectToJson(merMap));
        if (null == merMap || merMap.isEmpty()) {
            log.info("商户不存在");
            return CommonResult.build(403, "商户不存在");
        }
        int merGrade = Integer.parseInt(StringUtil.filterNull(merMap.get("mer_grade")));
        String distribSwitch = StringUtil.filterNull(merMap.get("trade_distrib_switch"));
        if (merGrade == 1) {
            //顶级商户的订单不参与分销
            distribSwitch = Constants.IS_NOT_NEED_DISTRIB;
        }

        //获取卡信息
        Map<String, Object> cardMap = cardService.getCardManageByCardNo(cardNo);
        log.info(cardNo + "对应的卡片编号对象：" + JsonUtil.objectToJson(cardMap));
        if (null == cardMap || cardMap.isEmpty()) {
            return CommonResult.build(403, "卡信息不存在");
        }
        String mobileNo = StringUtil.filterNull(cardMap.get("mobile_no"));
        String accountNo = StringUtil.filterNull(cardMap.get("account_no"));
        String accountName = StringUtil.filterNull(cardMap.get("account_name"));
        String idCardNo = StringUtil.filterNull(cardMap.get("id_card_no"));
        String cardType = StringUtil.filterNull(cardMap.get("card_type"));

        //获取通道信息
        Map<String, Object> routeChannel = WebUtil.getPayChannelInfo(acqCode);
        String acqMerchantNo = StringUtil.filterNull(routeChannel.get("pay_merchant_no"));
        String acqFeeRate = StringUtil.filterNull(routeChannel.get("trade_fee_rate"));

        //判断当前明细编号是否是成功状态，如果是成功状态，则不允许新增交易订单记录了
        RepayPlanDetail detail = planDetailService.getDetailByPlanNo(planNo);
        log.info(planNo + "对应的还款明细信息：" + JsonUtil.objectToJson(detail));
        if (detail != null && !Constants.PLAN_DETAIL_STATUS_SUCCESS.equals(detail.getPlanStatus())) {

            String orderNo = "";
            String orderDate = "";
            //1、先判断当前计划编号是否已存在交易订单，避免重复交易
            PayOrder payOrder = payOrderService.getPayOrderByService(Constants.PAY_ORDER_SERVICE_REPAY, planNo);
            if (null == payOrder || !Constants.ORDER_TRANS_STATUS_SUCCESS.equals(StringUtil.filterNull(payOrder.getTransStatus()))) {

                String batchNo = detail.getBatchNo();
                //获取明细对应还款计划
                RepayPlan plan = planService.getRepayPlanByBatchNo(detail.getBatchNo());
                String repayType = plan.getRepayType();
                BigDecimal merFeerate = plan.getMerFeeRate();

                orderNo = WebUtil.nextUniqueSeqNo("t_pay_order", Constants.REPAY_TYPE_QUICK.equals(repayType) ? "QPO" : "PPO", 20);
                orderDate = DateUtil.getDateTime();

                BigDecimal transFee = new BigDecimal(transAmount).multiply(merFeerate).setScale(2, BigDecimal.ROUND_UP);
                BigDecimal acqFee = new BigDecimal(transAmount).multiply(new BigDecimal(acqFeeRate)).setScale(2, BigDecimal.ROUND_UP);

                //获取代理商费率节点信息
                Map<String, String> agentNodeFeeMap = merchantService.getAgentNodeFeeByMerNo(merchantNo, repayType);
                if (null == agentNodeFeeMap || agentNodeFeeMap.isEmpty()) {
                    return CommonResult.build(403, "代理商成本有误");
                }
                String agentFeeRate = agentNodeFeeMap.get("agentFeeRate");

                payOrder = new PayOrder();
                payOrder.setMerchantNo(merchantNo);
                payOrder.setOrderNo(orderNo);
                payOrder.setCardNo(cardNo);
                payOrder.setAccountNo(accountNo);
                payOrder.setAccountName(accountName);
                payOrder.setCardType(cardType);
                payOrder.setRepayType(repayType);
                payOrder.setService(Constants.PAY_ORDER_SERVICE_REPAY);
                payOrder.setServiceOrderNo(planNo);
                payOrder.setTransAmount(new BigDecimal(transAmount));
                payOrder.setTransFee(transFee);
                payOrder.setTransFeeRate(merFeerate.toString());
                payOrder.setAgentFeeRate(agentFeeRate);
                payOrder.setAcqCode(acqCode);
                payOrder.setAcqMerchantNo(acqMerchantNo);
                payOrder.setAcqFee(acqFee);
                payOrder.setAcqFeeRate(acqFeeRate);
                payOrder.setIsNeedProfit(Constants.IS_NEED_PROFIT);
                payOrder.setIsNeedDistrib(distribSwitch);
                payOrder.setIsPlatProfit(Constants.IS_PLAT_PROFIT);

                log.info("计划明细编号：" + planNo + "明细消费新增交易订单：" + JsonUtil.objectToJson(payOrder));
                int count = payOrderService.savePayOrder(payOrder);
                log.info("计划明细编号：" + planNo + "明细消费新增交易订单影响的行数：" + count);
                if (count < 1) {
                    throw new RuntimeException("计划明细编号：" + planNo + "明细消费新增交易订单失败");
                }
                //计划明细操作次数加一次
                count = planDetailService.incrementDetailCount(planNo);
                log.info("计划编号：" + planNo + "操作次数加一影响的行数：" + count);
                if (count < 1) {
                    throw new RuntimeException("修改计划明细编号：" + planNo + "操作次数失败");
                }
            } else {
                orderNo = payOrder.getOrderNo();
                orderDate = DateUtil.formatDateTime(payOrder.getCreateTime());
            }

            Map<String, String> resMap = new HashMap<>();
            resMap.put("orderNo", orderNo);
            resMap.put("orderDate", orderDate);

            return CommonResult.ok(resMap);
        } else {
            return CommonResult.build(403, "明细编号：" + planNo + "已经是成功状态，不能再次消费");
        }
    }

    /**
     * 订单成功后代理商分润入账
     *
     * @param orderNo
     * @return
     */
    @Override
    @Transactional
    public CommonResult orderSuccToAgentProfit(String orderNo) throws Exception {

        PayOrder payOrder = payOrderService.getPayOrderByOrderNo(orderNo);
        log.info("交易订单号[{}]成功后数据库对象信息[{}]", new Object[]{orderNo, JsonUtil.objectToJson(payOrder)});
        if (payOrder == null) {
            return CommonResult.build(403, "订单不存在");
        }
        String orderStatus = payOrder.getTransStatus();
        if (!Constants.ORDER_TRANS_STATUS_SUCCESS.equals(orderStatus)) {
            log.info("交易订单[{}]状态非成功，不能进行分润", new Object[]{orderNo});
            return CommonResult.build(403, "订单状态非成功，不能进行分润");
        }
        String isNeedProfit = payOrder.getIsNeedProfit();
        String haveProfit = payOrder.getHaveProfit();
        if (!Constants.IS_NEED_PROFIT.equals(isNeedProfit)) {
            log.info("交易订单[{}]无需进行分润", new Object[]{orderNo});
            return CommonResult.build(403, "此订单不需要分润");
        }
        if (Constants.HAVE_PROFIT.equals(haveProfit)) {
            log.info("交易订单[{}]已进行分润，不能再次分润", new Object[]{orderNo});
            return CommonResult.build(403, "此订单已计算分润");
        }
        BigDecimal transAmount = payOrder.getTransAmount();
        Date transTime = payOrder.getTransTime();
        String repayType = payOrder.getRepayType();
        String merchantNo = payOrder.getMerchantNo();
        //获取商户费率信息和代理商成本信息
        String merFeeRateStr = payOrder.getTransFeeRate();
        String agentFeeRateJsonStr = payOrder.getAgentFeeRate();
        if (StringUtils.isBlank(merFeeRateStr) || StringUtils.isBlank(agentFeeRateJsonStr)) {
            log.info("交易订单[{}]商户费率[{}]或代理商成本[{}]信息有误，不能进行分润", new Object[]{orderNo, merFeeRateStr, agentFeeRateJsonStr});
            return CommonResult.build(403, "商户费率或代理商成本信息有误，不能计算分润");
        }
        BigDecimal merFeeRate = new BigDecimal(merFeeRateStr);
        JSONObject agentFeeRateJson = null;
        try {
            agentFeeRateJson = JSONObject.parseObject(agentFeeRateJsonStr);
        } catch (Exception e) {
            log.info("交易订单[{}]代理商节点成本[{}]信息有误，不能进行分销", new Object[]{orderNo, agentFeeRateJsonStr});
            return CommonResult.build(403, "代理商节点成本信息有误，不能计算分润");
        }
        //获取商户信息
        Map<String, Object> merMapInfo = merchantService.getMerInfoByMerNo(merchantNo);
        log.info("交易订单[{}]商户号[{}]对应商户信息[{}]", new Object[]{orderNo, merchantNo, JsonUtil.objectToJson(merMapInfo)});
        if (null == merMapInfo || merMapInfo.isEmpty()) {
            return CommonResult.build(403, "订单所属商户信息不存在");
        }
        String oemType = StringUtil.filterNull(merMapInfo.get("oem_type"));
        String agentNodeStr = StringUtil.filterNull(merMapInfo.get("agent_node"));
        String merAgentNo = StringUtil.filterNull(merMapInfo.get("agent_no"));
        if (StringUtils.isBlank(agentNodeStr)) {
            return CommonResult.build(403, "订单商户代理商节点信息有误，不能进行分润");
        }
        String[] nodeArray = agentNodeStr.split("-");

        String profitMerNo = "", agentFeeRateStr = "";
        String profitMerType = Constants.MER_TYPE_AGENT;
        BigDecimal agentFeeRate = BigDecimal.ZERO;
        BigDecimal agentAccountRatio = BigDecimal.ZERO;
        BigDecimal nextAgentFeeRate = BigDecimal.ZERO;
        BigDecimal feeRateDiff = BigDecimal.ZERO;
        Map<String, Object> agentFeeMapInfo = null;
        ProfitDetail profitDetail;

        String profitServiceType = Constants.REPAY_TYPE_QUICK.equals(repayType) ? Constants.PROFIT_SERVICE_QUICK_PAY : Constants.PROFIT_SERVICE_PERFECT_PAY;

        boolean isComplete = false;

        for (int index = nodeArray.length - 1; index >= 0; index--) {

            profitMerNo = nodeArray[index];

            agentFeeRateStr = agentFeeRateJson.getString(profitMerNo);
            if (StringUtils.isBlank(agentFeeRateStr)) {
                log.info("交易订单[{}]代理商节点[{}]对应代理商成本为空，不能计算分润", new Object[]{orderNo, profitMerNo});
                throw new RuntimeException("交易订单" + orderNo + "代理商节点" + profitMerNo + "成本信息为空");
            }
            agentFeeRate = new BigDecimal(agentFeeRateStr);

            //获取代理商对应的服务成本
            agentFeeMapInfo = merFeeService.getMerFeeByMerNoAndOemType(profitMerType, profitMerNo, oemType);
            log.info("交易订单[{}]代理商节点[{}]对应代理商成本信息[{}]", new Object[]{orderNo, profitMerNo, JsonUtil.objectToJson(agentFeeMapInfo)});
            if (agentFeeMapInfo == null || agentFeeMapInfo.isEmpty()) {
                throw new RuntimeException("交易订单" + orderNo + "代理商节点" + profitMerNo + "成本信息为空");
            }
            //代理商入账比例
            agentAccountRatio = StringUtil.filterNull(agentFeeMapInfo.get("account_ratio")) == null ? new BigDecimal("100") : new BigDecimal(StringUtil.filterNull(agentFeeMapInfo.get("account_ratio")));
            //成本费率差
            if (index == nodeArray.length - 1) {
                feeRateDiff = merFeeRate.subtract(agentFeeRate);
            } else {
                feeRateDiff = nextAgentFeeRate.subtract(agentFeeRate);
            }
            //计算出的分润金额
            BigDecimal profitAmount = transAmount.multiply(feeRateDiff).multiply(agentAccountRatio).divide(new BigDecimal("100")).setScale(2, BigDecimal.ROUND_DOWN);

            //查询是否已存在收益明细
            profitDetail = profitService.getProfitDetailByProfitMerAndService(profitMerType, profitMerNo, profitServiceType, orderNo);
            if (null != profitDetail) {
                log.info("交易订单[{}]收益代理商编号[{}]已存在收益明细", new Object[]{orderNo, profitMerNo});
                continue;
            }
            //保存收益明细
            String profitNo = WebUtil.nextUniqueSeqNo("t_profit_detail", "PDN", 20);
            profitDetail = new ProfitDetail();
            profitDetail.setProfitNo(profitNo);
            profitDetail.setProfitMerType(profitMerType);
            profitDetail.setProfitMerNo(profitMerNo);
            profitDetail.setSourceMerType(Constants.MER_TYPE_MERCHANT);
            profitDetail.setSourceMerNo(merchantNo);
            profitDetail.setAgentNo(merAgentNo);
            profitDetail.setServiceType(profitServiceType);
            profitDetail.setServiceOrderNo(orderNo);
            profitDetail.setTransAmount(transAmount);
            profitDetail.setProfitAmount(profitAmount);
            profitDetail.setMerFeeRate(merFeeRate);
            profitDetail.setAgentFeeRate(agentFeeRateStr);
            profitDetail.setAllowIncome(Constants.ALLOW_INCOME_NEED);
            profitDetail.setIncomeStatus(Constants.INCOME_STATUS_FAIL);

            if (feeRateDiff.compareTo(BigDecimal.ZERO) < 0) {
                profitDetail.setAllowIncome(Constants.ALLOW_INCOME_NOT_NEED);
                profitDetail.setRemark("当前上下级节点成本差" + feeRateDiff + "产生倒挂，不能入账");
            }

            int saveCount = profitService.saveProfitDetail(profitDetail);
            log.info("交易订单[{}]收益代理商编号[{}]保存收益明细影响的行数[{}]", new Object[]{orderNo, profitMerNo, saveCount});
            if (saveCount < 1) {
                throw new RuntimeException("交易订单" + orderNo + "收益代理商编号" + profitMerNo + "保存收益明细失败");
            }

            if (Constants.ALLOW_INCOME_NEED.equals(profitDetail.getAllowIncome())) {
                //入账操作
                String balanceRemark = "交易订单" + orderNo + "代理商编号" + profitMerNo + "分润收益";
                CommonResult balanceRes = balanceOperService.updateBalance(profitMerNo, profitMerType, profitAmount, Constants.BALANCE_HIS_TRANS_TYPE_IN, Constants.BALANCE_HIS_TYPE_CURR,
                        Constants.BALANCE_HIS_SERVICE_PROFIT, profitNo, balanceRemark, Constants.BALANCE_CHANNEL_DAIFU);
                if (balanceRes.getStatus() == 200) {
                    //回写收益入账状态
                    profitService.updateIncomeStatus(profitNo);
                }
            }
            if (index == 0) {
                isComplete = true;
            }
            nextAgentFeeRate = agentFeeRate;
        }
        if (isComplete) {
            //回写订单分润状态
            int updateCount = payOrderService.updatePayOrderProfitStatus(orderNo);
            log.info("交易订单[{}]修改分润状态影响的行数[{}]", new Object[]{orderNo, updateCount});
            if (updateCount < 1) {
                throw new RuntimeException("交易订单" + orderNo + "计算代理商分润失败");
            }
        }
        return CommonResult.ok();
    }

    /**
     * 订单成功后商户分销入账
     *
     * @param orderNo
     * @return
     */
    @Override
    @Transactional
    public CommonResult orderSuccToMerDistrib(String orderNo) throws Exception {

        PayOrder payOrder = payOrderService.getPayOrderByOrderNo(orderNo);
        log.info("交易订单号[{}]成功后数据库对象信息[{}]", new Object[]{orderNo, JsonUtil.objectToJson(payOrder)});
        if (payOrder == null) {
            return CommonResult.build(403, "订单不存在");
        }
        String orderStatus = payOrder.getTransStatus();
        if (!Constants.ORDER_TRANS_STATUS_SUCCESS.equals(orderStatus)) {
            log.info("交易订单[{}]状态非成功，不能进行分销", new Object[]{orderNo});
            return CommonResult.build(403, "订单状态非成功，不能进行分销");
        }
        String isNeedDistrib = payOrder.getIsNeedDistrib();
        String haveDistrib = payOrder.getHaveDistrib();
        if (!Constants.IS_NEED_DISTRIB.equals(isNeedDistrib)) {
            log.info("交易订单[{}]无需进行分销", new Object[]{orderNo});
            return CommonResult.build(403, "此订单不需要分销");
        }
        if (Constants.HAVE_DISTRIB.equals(haveDistrib)) {
            log.info("交易订单[{}]已进行分销，不能再次分销", new Object[]{orderNo});
            return CommonResult.build(403, "此订单已计算分销");
        }
        BigDecimal transAmount = payOrder.getTransAmount();
        Date transTime = payOrder.getTransTime();
        String merchantNo = payOrder.getMerchantNo();
        String acqCode = payOrder.getAcqCode();

        //获取商户费率信息和代理商成本信息
        String merFeeRateStr = payOrder.getTransFeeRate();
        String agentFeeRateJsonStr = payOrder.getAgentFeeRate();
        if (StringUtils.isBlank(merFeeRateStr) || StringUtils.isBlank(agentFeeRateJsonStr)) {
            log.info("交易订单[{}]商户费率[{}]或代理商节点成本[{}]信息有误，不能进行分销", new Object[]{orderNo, merFeeRateStr, agentFeeRateJsonStr});
            return CommonResult.build(403, "商户费率或代理商成本信息有误，不能计算分销");
        }
        BigDecimal merFeeRate = new BigDecimal(merFeeRateStr);
        JSONObject agentFeeRateJson = null;
        try {
            agentFeeRateJson = JSONObject.parseObject(agentFeeRateJsonStr);
        } catch (Exception e) {
            log.info("交易订单[{}]代理商节点成本[{}]信息有误，不能进行分销", new Object[]{orderNo, agentFeeRateJsonStr});
            return CommonResult.build(403, "代理商节点成本信息有误，不能计算分润");
        }

        //获取商户信息
        Map<String, Object> merMapInfo = merchantService.getMerInfoByMerNo(merchantNo);
        log.info("交易订单[{}]商户号[{}]对应商户信息[{}]", new Object[]{orderNo, merchantNo, JsonUtil.objectToJson(merMapInfo)});
        if (null == merMapInfo || merMapInfo.isEmpty()) {
            return CommonResult.build(403, "订单所属商户信息不存在");
        }
        String oemType = StringUtil.filterNull(merMapInfo.get("oem_type"));
        String oneAgentNo = StringUtil.filterNull(merMapInfo.get("one_agent_no"));
        String merAgentNo = StringUtil.filterNull(merMapInfo.get("agent_no"));
        String merNode = StringUtil.filterNull(merMapInfo.get("mer_node"));
        int merGrade = Integer.parseInt(StringUtil.filterNull(merMapInfo.get("mer_grade")));
        if (StringUtil.isBlank(oneAgentNo, merAgentNo, merNode)) {
            return CommonResult.build(403, "订单商户代理商节点或商户节点信息有误，不能进行分销");
        }
        if (merGrade == 1) {
            return CommonResult.build(403, "顶级商户的订单不参与分销");
        }
        //获取一级代理商的成本
        String oneAgentFeeRateStr = agentFeeRateJson.getString(oneAgentNo);
        if (StringUtils.isBlank(oneAgentFeeRateStr)) {
            return CommonResult.build(403, "一级代理成本为空，不能计算分销收益");
        }
        BigDecimal oneAgentFeeRate = new BigDecimal(oneAgentFeeRateStr);

        //获取平台分销收益成本
        String distribProfitRateStr = WebUtil.getSysValue("DISTRIB_PROFIT_RATE");
        log.info("交易订单[{}]系统当前平台分销收益成本[{}]", new Object[]{orderNo, distribProfitRateStr});
        if (StringUtils.isBlank(distribProfitRateStr)) {
            return CommonResult.build(403, "平台分销收益成本为空，不能计算分销");
        }
        BigDecimal distribProfitRate = new BigDecimal(distribProfitRateStr);

        //计算分销收益总额，（一级代理成本－平台分销收益成本）*交易总额
        BigDecimal distribTotalAmount = (oneAgentFeeRate.subtract(distribProfitRate)).multiply(transAmount).setScale(2, BigDecimal.ROUND_DOWN);
        log.info("交易订单[{}]计算分销收益总金额为[{}]", new Object[]{orderNo, distribTotalAmount});
        //获取分销层级数
        String distribNumStr = WebUtil.getSysValue("MER_DISTRIB_NUM");
        log.info("交易订单[{}]系统当前商户可分销层级数[{}]", new Object[]{orderNo, distribNumStr});
        if (StringUtils.isBlank(distribNumStr)) {
            CommonResult.build(403, "当前系统不支持多级分销");
        }

        //循环遍历商户节点，顶级商户做的交易不参与分销，所以数组长度必须大于１，且从上一级商户往上算
        String[] nodeArray = merNode.split("-");
        if (nodeArray.length < 2) {
            return CommonResult.build(403, "顶级商户的订单不参与分销");
        }

        int updateCount;
        String nodeMerNo = "", merRankCode = "", merRankValueStr = "";
        int currMerGrade = 1;//区分商户级别，这里指上一级，上二级，以此类推
        BigDecimal merLevelProfitRate = BigDecimal.ZERO;
        BigDecimal merDistribAmount = BigDecimal.ZERO;

        boolean isComplete = false;

        for (int index = nodeArray.length - 2; index >= 0; index--) {

            nodeMerNo = nodeArray[index];
            //获取当前节点商户信息
            merMapInfo = merchantService.getMerInfoByMerNo(merchantNo);
            log.info("交易订单[{}]所属商户号[{}]上[{}]级商户[{}]信息[{}]", new Object[]{orderNo, merchantNo, currMerGrade, nodeMerNo, merMapInfo});
            if (merMapInfo == null || merMapInfo.isEmpty()) {
                continue;
            }
            merRankCode = StringUtil.filterNull(merMapInfo.get("rank_code"));
            merRankCode = StringUtils.isBlank(merRankCode) ? Constants.RANK_CODE_SILVER : merRankCode;
            //获取当前级别的分销比例
            merRankValueStr = rankService.getRankConfigByOemAndCodeAndService(oemType, merRankCode, currMerGrade + "LevelProfitRate");
            log.info("交易订单[{}]所属商户号[{}]上[{}]级商户[{}]配置的分销比例[{}]", new Object[]{orderNo, merchantNo, currMerGrade, nodeMerNo, merRankValueStr});
            if (StringUtils.isBlank(merRankValueStr)) {
                continue;
            }
            try {
                merLevelProfitRate = new BigDecimal(merRankValueStr);
            } catch (Exception e) {
                log.info("交易订单[{}]所属商户号[{}]上[{}]级商户[{}]配置的分销比例[{}]异常", new Object[]{orderNo, merchantNo, currMerGrade, nodeMerNo, merRankValueStr});
                continue;
            }
            merDistribAmount = distribTotalAmount.multiply(merLevelProfitRate).setScale(2, BigDecimal.ROUND_DOWN);

            //查询是否已存在收益明细
            ProfitDetail profitDetail = profitService.getProfitDetailByProfitMerAndService(Constants.MER_TYPE_MERCHANT, nodeMerNo, Constants.PROFIT_SERVICE_DISTRIB_PAY, orderNo);
            if (null != profitDetail) {
                log.info("交易订单[{}]分销收益商户号[{}]已存在收益明细", new Object[]{orderNo, nodeMerNo});
                continue;
            }
            //保存收益明细
            String profitNo = WebUtil.nextUniqueSeqNo("t_profit_detail", "PDMP", 20);
            profitDetail = new ProfitDetail();
            profitDetail.setProfitNo(profitNo);
            profitDetail.setProfitMerType(Constants.MER_TYPE_MERCHANT);
            profitDetail.setProfitMerNo(nodeMerNo);
            profitDetail.setSourceMerType(Constants.MER_TYPE_MERCHANT);
            profitDetail.setSourceMerNo(merchantNo);
            profitDetail.setAgentNo(merAgentNo);
            profitDetail.setServiceType(Constants.PROFIT_SERVICE_DISTRIB_PAY);
            profitDetail.setServiceOrderNo(orderNo);
            profitDetail.setTransAmount(transAmount);
            profitDetail.setProfitAmount(merDistribAmount);
            profitDetail.setMerFeeRate(merLevelProfitRate);
            profitDetail.setAgentFeeRate(oneAgentFeeRate + "/" + distribProfitRate);
            profitDetail.setAllowIncome(Constants.ALLOW_INCOME_NEED);
            profitDetail.setIncomeStatus(Constants.INCOME_STATUS_FAIL);

            if (merLevelProfitRate.compareTo(BigDecimal.ONE) > 0) {
                profitDetail.setAllowIncome(Constants.ALLOW_INCOME_NOT_NEED);
                profitDetail.setRemark("当前商户分销比例大于1，不能入账");
            }

            int saveCount = profitService.saveProfitDetail(profitDetail);
            log.info("交易订单[{}]分销收益商户号[{}]保存收益明细影响的行数[{}]", new Object[]{orderNo, nodeMerNo, saveCount});
            if (saveCount < 1) {
                throw new RuntimeException("交易订单" + orderNo + "分销收益商户号" + nodeMerNo + "保存收益明细失败");
            }

            if (Constants.ALLOW_INCOME_NEED.equals(profitDetail.getAllowIncome())) {
                //入账操作
                String balanceRemark = "交易订单" + orderNo + "分销收益商户号" + nodeMerNo + "分润收益";
                CommonResult balanceRes = balanceOperService.updateBalance(nodeMerNo, Constants.MER_TYPE_MERCHANT, merDistribAmount, Constants.BALANCE_HIS_TRANS_TYPE_IN, Constants.BALANCE_HIS_TYPE_CURR,
                        Constants.BALANCE_HIS_SERVICE_TRADE, profitNo, balanceRemark, Constants.BALANCE_CHANNEL_DAIFU);
                if (balanceRes.getStatus() == 200) {
                    //回写分销入账状态
                    profitService.updateIncomeStatus(profitNo);
                }
            }
            if (currMerGrade > Integer.parseInt(distribNumStr) || index == 0) {
                isComplete = true;
                break;
            }
            currMerGrade++;
        }
        if (isComplete) {
            //回写订单分销状态
            updateCount = payOrderService.updatePayOrderDistribStatus(orderNo);
            log.info("交易订单[{}]修改分销状态影响的行数[{}]", new Object[]{orderNo, updateCount});
            if (updateCount < 1) {
                throw new RuntimeException("交易订单" + orderNo + "计算商户分销失败");
            }
        }
        return CommonResult.ok();
    }

    /**
     * 订单成功后计算平台收益入账
     *
     * @param orderNo
     * @return
     */
    @Override
    @Transactional
    public CommonResult orderSuccToPlatProfit(String orderNo) throws Exception {

        PayOrder payOrder = payOrderService.getPayOrderByOrderNo(orderNo);
        log.info("交易订单号[{}]成功后数据库对象信息[{}]", new Object[]{orderNo, JsonUtil.objectToJson(payOrder)});
        if (payOrder == null) {
            return CommonResult.build(403, "订单不存在");
        }
        String orderStatus = payOrder.getTransStatus();
        if (!Constants.ORDER_TRANS_STATUS_SUCCESS.equals(orderStatus)) {
            log.info("交易订单[{}]状态非成功，不能进行分销", new Object[]{orderNo});
            return CommonResult.build(403, "订单状态非成功，不能进行分销");
        }
        String isPlatProfit = payOrder.getIsPlatProfit();
        String havePlatProfit = payOrder.getHavePlatProfit();
        if (!Constants.IS_PLAT_PROFIT.equals(isPlatProfit)) {
            log.info("交易订单[{}]无需计算平台收益", new Object[]{orderNo});
            return CommonResult.build(403, "此订单不需要计算平台收益");
        }
        if (Constants.HAVE_PLAT_PROFIT.equals(havePlatProfit)) {
            log.info("交易订单[{}]已计算平台收益", new Object[]{orderNo});
            return CommonResult.build(403, "此订单已计算平台收益");
        }
        BigDecimal transAmount = payOrder.getTransAmount();
        Date transTime = payOrder.getTransTime();
        String merchantNo = payOrder.getMerchantNo();
        String acqCode = payOrder.getAcqCode();

        //获取商户信息
        Map<String, Object> merMapInfo = merchantService.getMerInfoByMerNo(merchantNo);
        log.info("交易订单[{}]商户号[{}]对应商户信息[{}]", new Object[]{orderNo, merchantNo, JsonUtil.objectToJson(merMapInfo)});
        if (null == merMapInfo || merMapInfo.isEmpty()) {
            return CommonResult.build(403, "订单所属商户信息不存在");
        }
        String merAgentNo = StringUtil.filterNull(merMapInfo.get("agent_no"));

        //获取通道信息
        Map<String, Object> acqMapInfo = WebUtil.getPayChannelInfo(acqCode);
        log.info("交易订单[{}]通道编码[{}]对应通道信息[{}]", new Object[]{orderNo, acqCode, JsonUtil.objectToJson(acqMapInfo)});
        if (null == acqMapInfo || acqMapInfo.isEmpty()) {
            return CommonResult.build(403, "通道不存在，不能计算平台收益");
        }
        String acqFeeRateStr = StringUtil.filterNull(acqMapInfo.get("trade_fee_rate"));
        if (StringUtils.isBlank(acqFeeRateStr)) {
            return CommonResult.build(403, "通道成本为空，不能计算平台收益");
        }
        BigDecimal acqFeeRate = new BigDecimal(acqFeeRateStr);

        //获取平台分销收益成本
        String distribProfitRateStr = WebUtil.getSysValue("DISTRIB_PROFIT_RATE");
        log.info("交易订单[{}]系统当前平台分销收益成本[{}]", new Object[]{orderNo, distribProfitRateStr});
        if (StringUtils.isBlank(distribProfitRateStr)) {
            return CommonResult.build(403, "平台分销收益成本为空，不能计算平台收益");
        }
        BigDecimal distribProfitRate = new BigDecimal(distribProfitRateStr);

        int updateCount;

        //计算平台收益总额，（平台分销收益成本－通道成本）*交易总额
        BigDecimal platTotalProfitAmount = (distribProfitRate.subtract(acqFeeRate)).multiply(transAmount).setScale(2, BigDecimal.ROUND_DOWN);
        //查询是否已存在收益明细
        ProfitDetail profitDetail = profitService.getProfitDetailByProfitMerAndService(Constants.MER_TYPE_PLAT, Constants.PLAT_MER_NO, Constants.PROFIT_SERVICE_PLAT_PROFIT, orderNo);
        log.info("交易订单[{}]数据库平台收益记录[{}]", new Object[]{orderNo, JsonUtil.objectToJson(profitDetail)});
        if (null == profitDetail) {
            //平台收益暂时不作入账处理
            String profitNo = WebUtil.nextUniqueSeqNo("t_profit_detail", "PPO", 20);
            profitDetail = new ProfitDetail();
            profitDetail.setProfitNo(profitNo);
            profitDetail.setProfitMerType(Constants.MER_TYPE_PLAT);
            profitDetail.setProfitMerNo(Constants.PLAT_MER_NO);
            profitDetail.setSourceMerType(Constants.MER_TYPE_MERCHANT);
            profitDetail.setSourceMerNo(merchantNo);
            profitDetail.setAgentNo(merAgentNo);
            profitDetail.setServiceType(Constants.PROFIT_SERVICE_PLAT_PROFIT);
            profitDetail.setServiceOrderNo(orderNo);
            profitDetail.setTransAmount(transAmount);
            profitDetail.setProfitAmount(platTotalProfitAmount);
            profitDetail.setMerFeeRate(distribProfitRate);
            profitDetail.setAgentFeeRate(acqFeeRateStr);
            profitDetail.setAllowIncome(Constants.ALLOW_INCOME_NEED);
            profitDetail.setIncomeStatus(Constants.INCOME_STATUS_FAIL);
            profitDetail.setRemark("平台交易收益");

            updateCount = profitService.saveProfitDetail(profitDetail);
            log.info("交易订单[{}]保存平台收益明细影响的行数[{}]", new Object[]{orderNo, updateCount});
            if (updateCount < 1) {
                return CommonResult.build(403, "保存平台收益记录失败");
            }
            if (Constants.ALLOW_INCOME_NEED.equals(profitDetail.getAllowIncome())) {
                //入账操作
                String balanceRemark = "交易订单" + orderNo + "平台" + Constants.PLAT_MER_NO + "收益入账";
                CommonResult balanceRes = balanceOperService.updateBalance(Constants.PLAT_MER_NO, Constants.MER_TYPE_PLAT, platTotalProfitAmount, Constants.BALANCE_HIS_TRANS_TYPE_IN, Constants.BALANCE_HIS_TYPE_CURR,
                        Constants.BALANCE_HIS_SERVICE_TRADE, profitNo, balanceRemark, Constants.BALANCE_CHANNEL_DAIFU);
                if (balanceRes.getStatus() == 200) {
                    //回写分销入账状态
                    profitService.updateIncomeStatus(profitNo);
                }
            }
        }
        //修改订单平台收益状态
        updateCount = payOrderService.updatePayOrderPlatProfitStatus(orderNo);
        log.info("交易订单[{}]修改平台收益状态影响的行数[{}]", new Object[]{orderNo, updateCount});
        if (updateCount < 1) {
            throw new RuntimeException("交易订单" + orderNo + "计算平台收益异常");
        }
        return CommonResult.ok();
    }
}